#pragma once
#include <SimpleDef.h>
#include <Memory/Segmentation.h>
#include <IntExcept/IntExcept.h>
#include <Memory/Paging.h>
#include <Memory/Heap.h>

#define THREAD_READY (0)
#define THREAD_SUSPENDED (1)
#define THREAD_RUNNING (2)
#define THREAD_JOINED (3)
#define THREAD_EXITED (4)

typedef LPVOID LPTHREAD_START_ROUTINE; /* 线程入口地址 */
struct __ThreadControlBlock;
struct __TaskStateSegment;
struct __ProcessControlBlock;
struct __FileObject;
/* 
@brief 线程控制块
*/
typedef struct __ThreadControlBlock
{
    struct __ThreadControlBlock* lpPrev; /* 调度队列中的上一个线程 */
    struct __ThreadControlBlock* lpNext; /* 调度队列中的下一个线程 */
    struct __ProcessControlBlock* lpProcess; /* 线程所属的进程 */
    struct __ThreadControlBlock* lpPrevSibling; /* 队列中上一个兄弟线程 */
    struct __ThreadControlBlock* lpNextSibling; /* 队列中下一个兄弟线程 */
    BOOL bIsIdle; /* 是否为傀儡线程，傀儡线程不属于任何进程，在无线程可指派时上处理器运行 */
    DWORD dwProcessId; /* 所属进程 Id */
    DWORD dwThreadId; /* 线程 Id */
    LPVOID lpUserStack; /* 线程用户态堆栈 */
    LPVOID lpKernelStack; /* 线程使用的内核态堆栈，其大小固定为 8 KiB */
    DWORD dwUserStackSize; /* 线程堆栈大小 */
    LPTHREAD_START_ROUTINE lpStartAddress; /* 线程入口地址 */
    LPVOID lpParameter; /* 线程执行所需的参数 */
    DWORD dwPriority; /* 线程优先级 */
    int nTicks; /* 运行的时间片数量 */
    DWORD dwStatus; /* 线程状态 */
    IntExceptContext context; /* 线程被中断时的上下文 */
    DWORD dwLastError; /* 错误码 */
} ThreadControlBlock, *LPThreadControlBlock, *LPTCBQUEUE;

/*
@breif 任务状态段 TSS
*/
typedef struct __TaskStateSegment
{
    DWORD dwPreviousTasklink; /* 上一项任务的段选择子 */
    DWORD dwRing0ESP;
    DWORD dwRing0StaskSegment;
    DWORD dwRing1ESP;
    DWORD dwRing1StackSegment;
    DWORD dwRing2ESP;
    DWORD dwRing2StackSegment;
    DWORD dwCR3;
    DWORD dwEIP;
    DWORD dwEFLAGS;
    DWORD dwEAX, dwECX, dwEDX, dwEBX, dwESP, dwEBP, dwESI, dwEDI;
    DWORD dwES, dwCS, dwSS, dwDS, dwFS, dwGS;
    DWORD dwLDTSegmentSelector;
    WORD wDebugTrap;
    WORD wIOMapBaseAddress;
} TaskStateSegment, *LPTaskStateSegment;


/* 进程控制块 */
typedef struct __ProcessControlBlock
{
    struct __ProcessControlBlock* lpChildProcess; /* 孩子节点 */
    struct __ProcessControlBlock* lpSiblingProcess; /* 兄弟节点 */
    struct __ThreadControlBlock* lpThreadList; /* 进程拥有的诸线程 */
    LPSTR lpszName; /* 进程名 */
    LPSTR lpszExecPath; /* 可执行文件路径 */
    DWORD dwProcessId; /* 进程 Id */
    LPHeap lpHeap; /* 进程的堆，由各进程共享 */
    struct __FileObject* lpFileList; /* 打开的文件列表 */
    LPPageDirectoryEntry lpVirtualPageDirectory; /* 进程的页目录在主控页目录中对应的地址 */
    DWORD dwCR3; /* 进程的页表 */
} ProcessControlBlock, *LPProcessControlBlock;

#define MAKE_TASK_GATE_DESCRIPTOR(P, DPL, TSS_SELECTOR) MAKE_SEGMENT_DESCRIPTOR()

extern void RestoreThreadContext(DWORD dwESP);
LPProcessControlBlock SimpleCreateProcess
(
    LPCSTR lpApplicationName,
    LPCSTR lpCommandLine,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment
);
LPTCBQUEUE InitializeTCBQueue(void);
void AppendTCBToQueue(LPTCBQUEUE lpTCBQueue, LPThreadControlBlock lpTCB);
LPThreadControlBlock FetchTCBFromQueue(LPTCBQUEUE lpQueue);
LPThreadControlBlock SimpleCreateThread
(
    DWORD dwUserStackSize,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    DWORD dwCreationFlags
);
void ScheduleThread(IntExceptContext* lpIntExceptContext);
extern LPVOID ResolveELF32(LPVOID lpBase);
LPVOID LoadProgram(LPCSTR lpPath);
void InitializeMainThread(void);
LPThreadControlBlock GetCurrentThread();
LPProcessControlBlock GetCurrentProcess();
void SetLastError(DWORD dwErrorCode);
DWORD GetLastError();